using Box;
using Godot;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace Box;

public partial class ItemSelectTree : Tree
{
	[Signal]
	public delegate void onSelectEventHandler(string class_name,string class_file_path);

	public string FilterType {
		get {
			return filter_type;
		}
		set {
			filter_type = value;
			UpdateSelectTree();
		}
	}

	protected string filter_type = "";

	public struct NodeItem {
		public string ClassName;
		public string ClassFilePath;
	}

	public Dictionary<ulong,NodeItem> Nodes = new Dictionary<ulong, NodeItem>();
	
	Dictionary<string,TreeItem> groups = new Dictionary<string, TreeItem>();

	public override void _Ready()
	{
		ItemSelected += _onItemSelected;
	}

	public void UpdateSelectTree() {
		groups.Clear();
		Clear();
		//给未生成记号文件的文件生成记号文件
		var assembly = Assembly.GetExecutingAssembly();
		foreach(Type type in assembly.GetTypes()) {
			PTEItemSelectSettingAttribute item_select_setting = type.GetCustomAttribute<PTEItemSelectSettingAttribute>();
				
			if(item_select_setting != null) {
				if(item_select_setting.Type == FilterType) {
					//AddToGroup(type,item_select_setting);
					TryCreateTokenFile(type,item_select_setting);
				}
			}
		}

		//加载所有标记的类

		IterDir(ProcessTreeEditor.ProjectPath, (path,name) => {
			if(name.Find(".ptclass") != -1) {
				LoadTokenFile(path);
			}
		});
	}

	void IterDir(string path,Action<string,string> f) {
		DirAccess dir = DirAccess.Open(path);
		if(dir != null) {
			dir.ListDirBegin();
			
			string next = dir.GetNext();
			while(next != "") {
				if(dir.CurrentIsDir()) {
					IterDir($"{path}/{next}",f);
				} else {
					f($"{path}/{next}",next);
				}
				next = dir.GetNext();
			}
		}
	}

	public TreeItem GetGroup(string name) {
		if(!groups.ContainsKey(name)) {
			TreeItem new_grpup = CreateItem();
			new_grpup.SetText(0,name);
			groups[name] = new_grpup;
		}
		return groups[name];
	}

	public void AddToGroup(Type type,PTEItemSelectSettingAttribute setting) {
		TreeItem group = GetGroup(setting.Group);
		TreeItem item = group.CreateChild();
		item.SetText(0,setting.Name);
		Nodes[item.GetInstanceId()] = new NodeItem {
			ClassName = type.FullName,
			ClassFilePath = setting.FilePath
		};
	}

	public void AddToGroup(_PTCLASS_JSON json) {
		TreeItem group = GetGroup(json.group);
		TreeItem item = group.CreateChild();
		item.SetText(0,json.name);
		Nodes[item.GetInstanceId()] = new NodeItem {
			ClassName = json.class_full_name,
			ClassFilePath = json.path
		};
	}

	public struct _PTCLASS_JSON {
		public string type;
		public string name;
		public string path;
		public string group;
		public string class_full_name;
	}

	public static void TryCreateTokenFile(Type type,PTEItemSelectSettingAttribute setting) {
		string token_file_path = $"{setting.FilePath}.ptclass";
		if(!FileAccess.FileExists(token_file_path)) {
			GD.Print(token_file_path);
			_PTCLASS_JSON s = new _PTCLASS_JSON {
				type = setting.Type,
				name = setting.Name,
				path = setting.FilePath,
				group = setting.Group,
				class_full_name = type.FullName
			};
			string json_string = JsonConvert.SerializeObject(s);
			FileAccess json_file = FileAccess.Open(token_file_path,FileAccess.ModeFlags.WriteRead);
			json_file.StoreString(json_string);
			json_file.Flush();
			json_file.Close();
		}
	}

	public static void TryCreateTokenFile(string class_full_name,string type, string name,string group,string path) {
		string token_file_path = $"{path}.ptclass";
		if(!FileAccess.FileExists(token_file_path)) {
			GD.Print(token_file_path);
			_PTCLASS_JSON s = new _PTCLASS_JSON {
				type = type,
				name = name,
				path = path,
				group = group,
				class_full_name = class_full_name
			};
			string json_string =JsonConvert.SerializeObject(s);
			FileAccess json_file = FileAccess.Open(token_file_path,FileAccess.ModeFlags.WriteRead);
			json_file.StoreString(json_string);
			json_file.Flush();
			json_file.Close();
		}
	}

	public void LoadTokenFile(string path) {
		FileAccess json_file = FileAccess.Open(path,FileAccess.ModeFlags.Read);
		if(json_file.IsOpen()) {
			string json_string = json_file.GetAsText();
			_PTCLASS_JSON json = JsonConvert.DeserializeObject<_PTCLASS_JSON>(json_string);
			
			if(json.type == FilterType) {
				AddToGroup(json);
			}

			json_file.Close();
		}
	}


	public void _onItemSelected() {
		var item = GetSelected();
		if(Nodes.ContainsKey(item.GetInstanceId())) {
			var node_info = Nodes[item.GetInstanceId()];
			EmitSignal(nameof(onSelect),node_info.ClassName,node_info.ClassFilePath);
		}
	}
}
